package 基础语法.反射;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class 动态代理 {
    public static void main(String[] args) {
        MethodsNeedProxy mnp = ProxyUtil.createProxy(new CXK());
        mnp.dance();
        mnp.sing("只因你太每");
    }

}

class ProxyUtil {
    /**
     * 给一个CXK对象创建代理
     * 形参：被代理的对象
     * 返回值：代理后的对象
     * 
     * 需求：外面的人调用ProxyUtil.createProxy获取cxk的代理对象
     * 然后调用代理的sing和dance方法
     */
    public static MethodsNeedProxy createProxy(CXK cxk) {
        // 参数1： 用与指定用哪个类加载器，去加载生成的代理类：谁把当前的类加载，就让他把要代理的类也加载。
        // 参数2：指定接口，这些接口用于指定生成的代理长什么样，也就是有哪些方法:可以代理MethodsNeedProxy中的所有方法，还可以再去代理其他的方法，多写几个
        // 参数3：用来指定生成的代理对象要干什么事情
        MethodsNeedProxy mnp = (MethodsNeedProxy) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
                new Class[] { MethodsNeedProxy.class }, new InvocationHandler() {

                    @Override
                    // 参数1：代理的对象CXK
                    // 参数2：要运行的方法，指ProxyUtil.createProxy获取 cxk的代理对象后，使用代理对象调用的single或dance
                    // 参数3：参数2中，调用时 传递的参数的值
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if (method.getName().equals("sing"))

                {
                            System.out.println("唱歌前要打篮球，唱的是："+Arrays.toString(args));
                        } else if (method.getName().equals("dance")) {
                            System.out.println("跳舞前要打篮球," );
                        }
                        //return method.invoke(proxy, args);// 调用本身的方法,注意这里应该传入要代理的对象，而不是代理对象本身，否则会出现循环调用最终栈溢出
                        return method.invoke(cxk, args);

                    }

                });

        return mnp;
    }

}

interface MethodsNeedProxy {// 接口中定义想要代理的对象

    public void dance();

    public void sing(String s);
}

class CXK implements MethodsNeedProxy {// 让要代理的对象实现接口

    @Override
    public void dance() {
        System.out.println("cxk跳舞,");
    }

    @Override
    public void sing(String s) {
        System.out.println("cxk唱歌："+s);

    }

}